package alist

import (
	"alist-gui/res"
	"context"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"sync"
	"syscall"
)

type CmdAlist struct {
	Work    string
	ExeName string

	mu sync.Mutex
}

func NewCmdAlist() (*CmdAlist, error) {
	var exePath = filepath.Join(workDir, exeFileName)
	_, err := os.Stat(exePath)
	if err != nil && os.IsNotExist(err) {
		_ = os.Mkdir(workDir, os.ModePerm)
		fs, err := os.Create(exePath)
		if err != nil {
			return nil, nil
		}
		defer fs.Close()
		_, err = fs.Write(res.AlistRes)
		if err != nil {
			return nil, nil
		}
	} else if err != nil {
		return nil, err
	}

	return &CmdAlist{}, nil
}

func (c *CmdAlist) Start() string {
	c.mu.Lock()
	defer c.mu.Unlock()
	return c.command("start")
}

func (c *CmdAlist) Restart() string {
	c.mu.Lock()
	defer c.mu.Unlock()
	return c.command("restart")
}
func (c *CmdAlist) Stop() string {
	c.mu.Lock()
	defer c.mu.Unlock()
	return c.command("stop")
}

// Storage Manage storage
func (c *CmdAlist) Storage() string {
	c.mu.Lock()
	defer c.mu.Unlock()
	return c.command("storage", "disable")
}

// Version 版本号
func (c *CmdAlist) Version() string {
	c.mu.Lock()
	defer c.mu.Unlock()
	return c.command("version")
}

// ResetPassword 重新设置密码
func (c *CmdAlist) ResetPassword(password string) string {
	c.mu.Lock()
	defer c.mu.Unlock()
	return c.command("admin", "set", password)
}

// Admin 查看root账号信息
func (c *CmdAlist) Admin() string {
	c.mu.Lock()
	defer c.mu.Unlock()
	return c.command("admin")
}

func (c *CmdAlist) command(args ...string) string {
	ctx, cancel := context.WithCancel(context.TODO())
	defer cancel()

	cmd := exec.CommandContext(ctx, "./"+exeFileName, args...)
	cmd.Dir = workDir
	cmd.Cancel = func() error {
		if cancel != nil {
			cancel()
		}
		return cmd.Process.Kill()
	}
	// 关闭黑框
	cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
	// 输出
	stdout := NewIOReader(128)
	defer close(stdout.dataChan)

	cmd.Stdout = stdout
	cmd.Stderr = stdout
	//stdout, err := cmd.StdoutPipe()
	//if err != nil {
	//	return err.Error()
	//}
	//
	//defer stdout.Close()

	if err := cmd.Start(); err != nil {
		return err.Error()
	}

	//scanner := bufio.NewScanner(stdout)
	var out string
	//for scanner.Scan() {
	//	out += scanner.Text() + "\n"
	//}

	go func() {
		for bytes := range stdout.Chan() {
			out += string(bytes)
		}
	}()
	if err := cmd.Wait(); err != nil {
		return err.Error()
	}

	// ANSI escape codes的正则表达式
	re := regexp.MustCompile(`\033\[[0-9;]*m`)
	cleanStr := re.ReplaceAllString(out, " ")

	return cleanStr // + "\nok."
}
